package com.atguigu.search.thread;

import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.concurrent.*;

/**
 * 异步编排
 *
 * @Author ShiJieLin
 * @Date 2022/4/19 12:44
 * @Version 1.0
 */
@Slf4j
public class CompletableFutureTest {

    static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        /** runAsync(Runnable runnable,  Executor executor)
         *  使用指定的线程池执行, 是没有返回结果的
         */
        /*        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {

            log.info("当前线程：{}", Thread.currentThread().getId());

            int i = 10 / 5;

            log.info("运行结果：i = {}", i);

        }, executorService);*/

        log.info("Main方法开始");
        /** supplyAsync(Supplier<U> supplier, Executor executor)
         *  带返回值结果的线程，指定线程池
         */
         /*        CompletableFuture<Integer> async = CompletableFuture.supplyAsync(() -> {

            log.info("当前线程：{}", Thread.currentThread().getId());

            int i = 10 / 5;

            log.info("运行结果：i = {}", i);

            return i;
        }, executorService);
        Integer integer = async.get();*/

         /*        CompletableFuture<Void> exceptionally = CompletableFuture.runAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 5;
            log.info("运行结果：i = {}", i);
        }, executorService).whenComplete((result, exception) -> {
            log.info("运算结果：result = {}", result);
            log.info("异常结果：exception = {}", exception);
        });*/

        /*        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 5;
            log.info("运行结果：i = {}", i);
            return i;
        }, executorService).whenComplete((result, exception) -> {

            log.info("运算结果：result = {}", result);
            log.info("异常结果：exception = {}", exception);
        }).exceptionally(exception -> {

            log.info("异常结果：exception2 = {}", exception);
            return 10;
        });
        Integer integer = future.get();*/

        /*        CompletableFuture<Serializable> handle = CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 0;
            log.info("运行结果：i = {}", i);
            return i;
        }, executorService).handle((result, exception) -> {
            if (null != result) {
                return result;
            }
            if (null != exception) {
                return exception;
            }
            return 0;
        });
        Serializable serializable = handle.get();*/

/*        CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 5;
            log.info("运行结果：i = {}", i);
            return i;
        }, executorService).thenAcceptAsync((res) -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            log.info("thenAccept 运行结果：res = {}", res);
        }, executorService);
        */
/*        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 5;
            log.info("运行结果：i = {}", i);
            return i;
        }, executorService).thenApplyAsync((res) -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            log.info("thenApplyAsync 运行结果：res = {}", res);
            return res + "Hello";
        }, executorService);*/

/*        CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 5;
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("10 / 5 运行结果：i = {}", i);
            return i;
        }, executorService).thenRunAsync(() -> {

            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 + 5;
            log.info("10 + 5 运行结果：i = {}", i);
        }, executorService);*/
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 / 5;
            log.info("任务1：运行结果：i = {}", i);
            return i;
        }, executorService);

        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 * 5;
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("任务2：运行结果：i = {}", i);
            return i;
        }, executorService);

        CompletableFuture<Integer> future03 = CompletableFuture.supplyAsync(() -> {
            log.info("当前线程：{}", Thread.currentThread().getId());
            int i = 10 + 5;
            log.info("任务3：运行结果：i = {}", i);
            return i;
        }, executorService);

        /** runAfterBothAsync 得等待任务1和任务2都执行完成
         *  才会执行，如果1和2有异常那么 就不会执行

        future01.runAfterBothAsync(future02, () -> {

            log.info("任务3：等待任务1 和 任务2 执行完成，再执行");
        }, executorService);
         */

        /** thenAcceptBothAsync 等待任务1和任务2都执行完成
         *  获取到返回结果，进行处理，但是自己本身不返回结果

        future01.thenAcceptBothAsync(future02, (f1, f2) ->{
            log.info("任务3：运行结果：f1 + f2 = {}", f1 + f2);
        }, executorService);
         */

        /** thenCombineAsync 等待任务1和任务2都执行完成，
         *  获取1和2的任务结果，进行处理，自己本身也返回一个结果

        CompletableFuture<Integer> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            log.info("任务3：运行结果：f1 + f2 = {}", f1 + f2);
            return f1 + f2;
        }, executorService);
        */

        /** runAfterEitherAsync 等待任务1和任务2中任意一个完成
         *  就开始执行，不接受参数，不返回结果

        future01.runAfterEitherAsync(future02, () -> {
         log.info("任务3：等待任务1 和 任务2 其中任意一个执行完成，再执行");
        }, executorService);
         */

        /** acceptEitherAsync 等待任务1和任务2其中任意一个执行完成
         *  任务1和任务2的返回值得相同，接收一个参数(任务1或者任务2其中一个得返回结果)

        future01.acceptEitherAsync(future02, (res) -> {
            log.info("任务3：等待任务1 和 任务2 其中任意一个执行完成，再执行,res: {}", res);
        }, executorService);*/

        /** applyToEitherAsync 等待任务1和任务2其中任意一个执行完成，再执行
         *  任务1和任务2的返回参数类型得一致， 接收一个参数，
         *  自己本身也返回一个参数

        CompletableFuture<String> apply = future01.applyToEitherAsync(future02, (res) -> {
            log.info("任务3：等待任务1 和 任务2 其中任意一个执行完成，再执行,res: {}", res);
            return res + "HAHA";
        }, executorService);
         */

        /** CompletableFuture.anyOf 任务中有一个执行完成，就会执行
         *  allOf.get()或者 join 终止阻塞
         */
        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);

        allOf.get();

        log.info("Main方法结束" + allOf.get());
    }
}

